//
//  LoginViewModel.swift
//  App_Login
//
//  Created by 蒋晨成 on 2022/1/6.
//

import App_Common
import Center
import RxCocoa
import RxSwift
import UICore
import UIKit

class LoginViewModel: ViewModel, ViewModelType {
    private let mobile = BehaviorRelay<String>(value: RegisterCenter.mobile ?? "")
    private let agree = BehaviorRelay<Bool>(value: false)
    private let submitState = PublishSubject<HandleState>()
    private var disposeBag = DisposeBag()
}

extension LoginViewModel {
    struct Input {
        let mobile: Driver<String>
        let submitTap: Observable<Void>
        let agree: Observable<Void>
    }

    struct Output {
        let mobile: Observable<String>
        let submitButtonValid: Observable<Bool>
        let submitState: Driver<HandleState>
        let agree: Observable<Bool>
    }

    func transform(input: Input) -> Output {
        let submitButtonValid = bindSubmitButtonValid(input.mobile)
        handleSendSMS(input.submitTap)
        handleCheckBox(input.agree)
        return Output(
            mobile: mobile.asObservable(),
            submitButtonValid: submitButtonValid,
            submitState: submitState.asDriver(onErrorJustReturn: .failure(message: LoginModular.localizedString(key: "Verify.System.Error"))),
            agree: agree.asObservable()
        )
    }
}

private extension LoginViewModel {
    func bindSubmitButtonValid(_ observe: Driver<String>) -> Observable<Bool> {
        observe.asObservable()
            .distinctUntilChanged()
            .flatMapLatest { [weak self] string -> Observable<Bool> in
                guard let self = self else { return Observable.just(false) }
                RegisterCenter.mobile = string
                return self.checkMobile(string)
            }
            .asObservable()
    }

    func handleSendSMS(_ observe: Observable<Void>) {
        observe.subscribe(onNext: { [weak self] _ in
            self?.sendSMS()
        })
        .disposed(by: disposeBag)
    }

    func handleCheckBox(_ observe: Observable<Void>) {
        observe.subscribe(onNext: { [weak self] _ in
            guard let self = self else { return }
            let value = !self.agree.value
            self.agree.accept(value)
        })
        .disposed(by: disposeBag)
    }
}

private extension LoginViewModel {
    func checkMobile(_ mobile: String) -> Observable<Bool> {
        if mobile.count == 11 {
            return Observable.just(true)
        }
        return Observable.just(false)
    }

    func sendSMS() {
        guard let mobile = RegisterCenter.mobile else {
            submitState.onNext(.failure(message: LoginModular.localizedString(key: "Verify.Mobile.Empty")))
            return
        }

        guard agree.value else {
            submitState.onNext(.failure(message: LoginModular.localizedString(key: "Login.Tips.CheckBox.UnSelected")))
            return
        }

        let now = Date()
        guard now.timeIntervalSince1970 > RegisterCenter.expireIn?.timeIntervalSince1970 ?? 0 else {
            submitState.onNext(.failure(message: LoginModular.localizedString(key: "Verify.SMS.Frequently")))
            return
        }
        submitState.onNext(.doing)
        UserCenter.Sign.Mobile.sendSMS(mobile: mobile) { [weak self] result in
            switch result {
            case .success:
                RegisterCenter.expireIn = now.addingTimeInterval(60)
                self?.submitState.onNext(.success)
            case .failure(let error):
                self?.submitState.onNext(.failure(message: error.localizedDescription))
            }
        }
    }
}
